package com.gmsi_prototype;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

import BioHarnessSensor.BioharnessSensor;
import BioHarnessSensor.Global;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.BioSensor.SensorConnectionManager;

public class MainActivity extends Activity {


	public static double heartRate = 0.0;

	private RelativeLayout game_layer, menu_lib_layer;

	private Button btConnectBioHarness;
	private Button btConnectShimmer;

	private TextView tvBioHarnessData; 
	private TextView tvShimmerData;

	final private static int HRV = 0;
	final private static int BR = 1;
	final private static int HR = 2;
	final private static int SCL = 3;
	final private static int SCR = 4;

	private String debugTag = "DEBUG";

	private BluetoothAdapter mBluetoothAdapter;
	private ArrayAdapter<String> mArrayAdapter;

	private Handler dataDisplay = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			String data = null;
			switch (msg.what) {
			case BR:
				data = (String) msg.obj;
				Log.i("Data", "BR:" + data);

				tvBioHarnessData.setText("BR:" + data);
				break;

			case SCL:
				data = (String) msg.obj;
				tvShimmerData.setText("SCL:" + data);

				Log.i("Data", "SCL:" + data);
				break;
				
			case SCR:
				data = (String) msg.obj;
				Log.i("Data", "SCR:" + data);
				break;

			default:
				break;
			}
		}
	};

	private static final UUID UUID_BT  =
			UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");

	private UUID mSPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

	// Sensors
	BioharnessSensor bhSense;

	private void debugLog(Object obj) {
		Log.d(debugTag, String.valueOf(obj));
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_debug);
		game_layer = (RelativeLayout) findViewById(R.id.game_layer);
		menu_lib_layer = (RelativeLayout) findViewById(R.id.menu_lib_layer);

		menu_lib_layer.setVisibility(View.VISIBLE);
		game_layer.setVisibility(View.VISIBLE);

		Thread thread = new BlueToothThread();
		thread.start();
	}

	@Override
	protected void onStart() {
		super.onStart();


		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

		btConnectBioHarness = (Button) findViewById(R.id.btConnectBioHarness);
		btConnectBioHarness.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				// Search Devices and add to mArrayAdapter
				connectDevice("BH");
			}
		});

		btConnectShimmer = (Button) findViewById(R.id.btConnectShimmer);
		btConnectShimmer.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				// Search Devices and add to mArrayAdapter
				connectDevice("RN42");
			}
		});

		tvBioHarnessData = (TextView) findViewById(R.id.tvBioHarnessData);
		tvShimmerData = (TextView) findViewById(R.id.tvShimmerData);


	}


	public class BlueToothThread extends Thread{

		private SensorConnectionManager scm;
		private String[] sensor_names;

		/*
		 * initialize Sensor Connection Manager 
		 */
		public BlueToothThread() {
			mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

			scm = new SensorConnectionManager(mBluetoothAdapter);
			sensor_names = scm.getAvailableSensors();
		}

		public void run(){
			Looper.prepare();
			String[] temp = new String[]{ "BioHarness", "Shimmer" };
			Log.d("In BT Thread", temp.toString());
			try {
				scm.connectSensors(temp);
			} catch (IllegalArgumentException e) {
				Log.d("Exception",e.getMessage());
			}

			try {
				sleep(5000);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			for(int i = 0; i<3000; i++) {
				try {
					sleep(1000);
					double dataValue = scm.getRawData("BioHarness", "Heart Rate");
					Log.d("Data", "HR: " + dataValue);
					Message msg = new Message();
					msg.what = HR;
					msg.obj = (Object) String.valueOf(dataValue);
					dataDisplay.sendMessage(msg);
					
					double dataValue2 = scm.getRawData("Shimmer", "SCL");
					Log.d("Data", "SCL: " + dataValue2);
					Message msg2 = new Message();
					msg2.what = SCR;
					msg2.obj = (Object) String.valueOf(dataValue2);
					dataDisplay.sendMessage(msg2);
					
				} catch (IllegalArgumentException e) {
					Log.d("Exception", e.getMessage());
				} catch (InterruptedException e) {
					Log.d("Exception", e.getMessage());
				}
			}
			Looper.loop();
		}
	}


	@Override
	protected void onPause(){
		super.onPause();

		bhSense.disconnect();
	}

	// tvChoices allow to choose either tvBioHarnessData or tvShimmerData to display the data  
	protected void displayData(String data, int tvChoices) {
		Message msg = new Message();
		msg.obj = data;
		msg.what = tvChoices;
		dataDisplay.sendMessage(msg);
	}

	private void connectDevice(String deviceName) {

		// If the Android device doesn't support Bluetooth Service  
		if (mBluetoothAdapter == null) 
			return;

		int REQUEST_ENABLE_BT = 1;

		// Enable Bluetooth Device 
		if (!mBluetoothAdapter.enable()) {
			Intent enableBTintent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableBTintent, REQUEST_ENABLE_BT);
		}

		// Adding the current devices that are paired to the Android device
		Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
		// If there are paired devices
		if (pairedDevices.size() > 0) {
			// Loop through paired devices
			if(deviceName.startsWith("BH")) {
				for (BluetoothDevice device : pairedDevices) {
					// Add the name and address to an array adapter to show in a ListView
					if (device.getName().startsWith(deviceName)) {
						//						BTClient _btc = new BTClient(mBluetoothAdapter, device.getAddress());
						//						NewConnectedListener _NConnListener = new NewConnectedListener(DataHandler,DataHandler);
						//						_btc.addConnectedEventListener(_NConnListener);
						bhSense = new BioharnessSensor(mBluetoothAdapter);
						bhSense.connect();
					}
				}
			}
			if(deviceName.startsWith("RN42")) {
				for (BluetoothDevice device : pairedDevices) {
					// Add the name and address to an array adapter to show in a ListView
					if(device.getName().startsWith("RN42")) {
						debugLog("Shimmer sensor found");
						ConnectThreadShimmer shim = new ConnectThreadShimmer(device);
						shim.start();
					}
				}
			}
		}
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	/**
	 * Control the layer to be visible or not
	 * To see the connectivity in the background 
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub

		if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
			game_layer.setVisibility(View.GONE);
		}
		if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
			game_layer.setVisibility(View.VISIBLE);
		}
		return super.onKeyDown(keyCode, event);
	}

	/**
	 * This thread runs while attempting to make an outgoing connection
	 * with a device. It runs straight through; the connection either
	 * succeeds or fails.
	 */

	/*
	private class ConnectThread extends Thread {
		private String address;

		public ConnectThread(BluetoothDevice device) {
			address = device.getAddress();
			//			mmDevice = device;
			//			BluetoothSocket tmp = null;
			//			mSocketType = secure ? "Secure" : "Insecure";
			//
			//			// Get a BluetoothSocket for a connection with the
			//			// given BluetoothDevice
			//			try {
			//				if (secure) {
			//					tmp = device.createRfcommSocketToServiceRecord(
			//							MY_UUID_SECURE);
			//				} else {
			//					tmp = device.createInsecureRfcommSocketToServiceRecord(
			//							MY_UUID_INSECURE);
			//				}
			//			} catch (IOException e) {
			//				debugLog("Socket Type: " + mSocketType + "create() failed");
			//			}
			//			mmSocket = tmp;

		}

		public void run() {
			displayData("Connected", Update_BioHarness_data);
			BTClient _bt = new BTClient(mBluetoothAdapter, address);
			NewConnectedListener _NConnListener = new NewConnectedListener(DataHandler,DataHandler);
			_bt.addConnectedEventListener(_NConnListener);
			_bt.start();
			debugLog("Bioharness Device Connected");
			//			debugLog("BEGIN mConnectThread SocketType:" + mSocketType);
			//			setName("ConnectThread" + mSocketType);
			//
			//			// Make a connection to the BluetoothSocket
			//			try {
			//				// This is a blocking call and will only return on a
			//				// successful connection or an exception
			//				mmSocket.connect();
			//			} catch (IOException e) {
			//				// Close the socket
			//				try {
			//					mmSocket.close();
			//				} catch (IOException e2) {
			//					debugLog("unable to close() " + mSocketType +
			//							" socket during connection failure");
			//				}
			//				return;
			//			}
			//
			////			// Reset the ConnectThread because we're done
			////			synchronized (MainActivity.this) {
			////				mConnectThread = null;
			////			}
			//
			//			// Start the connected thread
			////			connected(mmSocket, mmDevice, mSocketType);
			//			
			//			ConnectedThread ct = new ConnectedThread(mmSocket, mSocketType);
			//			ct.start();
		}

		public void cancel() {
//			try {
//				mmSocket.close();
//			} catch (IOException e) {
//				debugLog("close() of connect " + mSocketType + " socket failed");
//			}
		}
	}
	 */
	/**
	 * This thread runs during a connection with a remote device.
	 * It handles all incoming and outgoing transmissions.
	 */
	private class ConnectedThread extends Thread {
		private final BluetoothSocket mmSocket;
		private final InputStream mmInStream;
		private final OutputStream mmOutStream;

		public ConnectedThread(BluetoothSocket socket, String socketType) {
			debugLog("create ConnectedThread: " + socketType);
			mmSocket = socket;
			InputStream tmpIn = null;
			OutputStream tmpOut = null;

			// Get the BluetoothSocket input and output streams
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) {
				debugLog("temp sockets not created");
			}

			mmInStream = tmpIn;
			mmOutStream = tmpOut;
		}

		public void run() {
			debugLog("BEGIN mConnectedThread");
			byte[] buffer = new byte[1024];
			int bytes = 0;

			// Keep listening to the InputStream while connected
			while (true) {
				//				try {
				//					// Read from the InputStream
				//					bytes = mmInStream.read(buffer);
				//
				//					// Send the obtained bytes to the UI Activity
				//					mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
				//					.sendToTarget();
				//				} catch (IOException e) {
				//					Log.e(TAG, "disconnected", e);
				//					connectionLost();
				//					// Start the service over to restart listening mode
				//					BluetoothChatService.this.start();
				//					break;
				//				}

				try {
					bytes = mmInStream.read(buffer);
					String data = Byte.toString((byte) bytes);
					debugLog(getName() + data);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		/**
		 * Write to the connected OutStream.
		 * @param buffer  The bytes to write
		 */
		//		public void write(byte[] buffer) {
		//			try {
		//				mmOutStream.write(buffer);
		//				// Share the sent message back to the UI Activity
		//				mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
		//				.sendToTarget();
		//			} catch (IOException e) {
		//				debugLog("Exception during write");
		//			}
		//		}

		public void cancel() {
			try {
				mmSocket.close();
			} catch (IOException e) {
				debugLog("close() of connect socket failed");
			}
		}
	}

	public class ConnectThreadShimmer extends Thread {
		private final BluetoothSocket mmSocket;
		private final BluetoothDevice mmDevice;

		public ConnectThreadShimmer(BluetoothDevice device) {
			mmDevice = device;
			BluetoothSocket tmp = null;

			// Get a BluetoothSocket for a connection with the
			// given BluetoothDevice
			try {
				tmp = device.createRfcommSocketToServiceRecord(mSPP_UUID);
			} catch (IOException e) {}
			mmSocket = tmp;
		}

		public void run() {
			setName("Shimmer ConnectThread");

			// Always cancel discovery because it will slow down a connection
			mBluetoothAdapter.cancelDiscovery();

			try {
				// Connect the device through the socket. This will block
				// until it succeeds or throws an exception
				mmSocket.connect();
			} catch (IOException connectException) {
				debugLog("Shimmer Connection failed");
				//            	connectionFailed();
				// Unable to connect; close the socket and get out
				try {
					mmSocket.close();
				} catch (IOException closeException) { }
				return;
			}

			debugLog("Shimmer Connected");


			// Reset the ConnectThread because we're done
			//            synchronized (MainActivity.this) {
			//                mConnectThread = null;
			//            }

			// Start the connected thread
			//            connected(mmSocket, mmDevice);

		}

		public void cancel() {
			try {
				mmSocket.close();
			} catch (IOException e) { }
		}
	}

}
